class SpringDouble extends egret.Sprite {
    private ball0: Ball
    private ball1: Ball
    private spring: number = 0.03
    private springLength: number = 100
    private friction: number = 0.90

    private touchX: number = 0
    private touchY: number = 0

    private draggingBall: Ball = null

    public constructor() {
        super()
        this.once(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this)
    }

    private onAddToStage(event: egret.Event) {
        this.ball0 = new Ball(20)
        this.ball0.x = Math.random() * this.stage.stageWidth
        this.ball0.y = Math.random() * this.stage.stageHeight
        this.ball0.touchEnabled = true
        this.addChild(this.ball0)

        this.ball1 = new Ball(20)
        this.ball1.x = Math.random() * this.stage.stageWidth
        this.ball1.y = Math.random() * this.stage.stageHeight
        this.ball1.touchEnabled = true
        this.addChild(this.ball1)
        
        this.stage.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.trackTouch, this)
        this.stage.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.onTouchStart, this)
        this.addEventListener(egret.Event.ENTER_FRAME, this.onEnterFrame, this)
    }

    private onEnterFrame(event: egret.Event) {
        this.springOn(this.ball0, this.ball1)
    }

    private springOn(ballA:Ball, ballB:Ball) {
        if (!ballA.dragging) {
            this.springTo(ballA, ballB)
        }

        if (!ballB.dragging) {
            this.springTo(ballB, ballA)
        }

        this.graphics.clear()
        this.graphics.lineStyle(1)
        this.graphics.moveTo(ballA.x, ballA.y)
        this.graphics.lineTo(ballB.x, ballB.y)
    }

    private springTo(ballA:Ball, ballB:Ball) {
        let dx = ballB.x - ballA.x
        let dy = ballB.y - ballA.y
        let angle = Math.atan2(dy, dx)
        let targetX = ballB.x - Math.cos(angle) * this.springLength
        let targetY = ballB.y - Math.sin(angle) * this.springLength
        ballA.vx += (targetX - ballA.x) * this.spring
        ballA.vy += (targetY - ballA.y) * this.spring
        ballA.vx *= this.friction
        ballA.vy *= this.friction
        ballA.x += ballA.vx
        ballA.y += ballA.vy
    }

    private trackTouch(evt:egret.TouchEvent) {
        this.touchX = evt.stageX
        this.touchY = evt.stageY
    }

    private onTouchStart(evt: egret.TouchEvent) {
        if (evt.target instanceof Ball) {
            this.draggingBall = evt.target
            this.draggingBall.dragging = true
        }
        this.stage.addEventListener(egret.TouchEvent.TOUCH_END, this.onTouchEnd, this)
        this.stage.addEventListener(egret.TouchEvent.TOUCH_MOVE, this.onTouchMove, this)
    }

    private onTouchEnd(evt: egret.TouchEvent) {
        if (this.draggingBall != null) {
            this.draggingBall.dragging = false
            this.draggingBall = null
        }
        
        this.stage.removeEventListener(egret.TouchEvent.TOUCH_END, this.onTouchEnd, this)
        this.stage.removeEventListener(egret.TouchEvent.TOUCH_MOVE, this.onTouchMove, this)
    }

    private onTouchMove(evt: egret.TouchEvent) {
        if (this.draggingBall == null && evt.target instanceof Ball) {
            this.draggingBall = evt.target
        }

        if (this.draggingBall == null) {
            return
        }
        this.draggingBall.x = evt.stageX
        this.draggingBall.y = evt.stageY
    }
}